if (left(address(), 5) = 'THOR.') then thorport = address()
else do
say 'As of the Thor 2.5 release SortMail can only be run from Thor.'
say 'Please read SortMail.guide for more information.'
exit(0)
end
/*
** Find Thor's path and open BBSREAD ARexx port
*/
if ~(open(tp, 'ENV:THOR/THORPATH', 'R')) then displayerror(30, 'SortMail', 'Couldn''t find Thor''s path.')
thorpath = readln(tp)
close(tp)
if ~(show('P', 'BBSREAD')) then do
address(command)
'Run >NIL: `GetEnv THOR/THORPath`bin/LoadBBSRead'
'WaitForPort BBSREAD'
if (rc ~= 0) then displayerror(30, 'SortMail', 'Couldn''t open BBSREAD''s ARexx port.')
end
/*
** See if another copy of SortMail is already running
*/
if (getclip('SM_Active') ~= '') then call notify('Another copy of SortMail is probably running.\nDo you want to continue?', 'Yes|No')
if (result = 0) then exit(0)
call setclip('SM_Active', 'True')
/*
** Determine how SortMail was started
*/
address(thorport)
'CURRENTSYSTEM STEM 'cursys
if (rc = 1) then call displayerror(20, 'SortMail', 'SortMail has to be run from inside a system.')
if (rc > 1) then call displayerror(30, 'SortMail', 'CURRENTSYSTEM: 'THOR.LASTERROR)
if (cursys.CONFNAME = '') then do
if (getclip('SM_Notified') = '') then do
call notify('As of Thor 2.5 mail is automatically sorted at the\ntime of import. This makes it unnecessary to run\nSortMail.br when entering a system.\n\nPlease remove the SortMail.br entry in this system''s\nconfiguration. You can find it in System\nConfiguration -> Files/Paths -> Entering System.\n\nSortMail.guide has more information.', 'Ok')
call setclip('SM_Notified', 'Done')
end
signal cleanup
end
/*
** Display some progress info
*/
address(thorport)
'OPENPROGRESS TITLE "SortMail.br 'version'" PT "Initializing..." AT "_Abort" PCW 40'
if (rc ~= 0) then call displayerror(30, 'SortMail', 'OPENPROGRESS: 'THOR.LASTERROR)
progwin = result
/*
** Utilize BBSRead's copyback buffer
*/
address(bbsread)
'BUFMODE COPYBACK'
/*
** Get system information
*/
address(bbsread)
'GETBBSDATA "'cursys.BBSNAME'" 'bbsdata
if (rc ~= 0) then call displayerror(30, 'SortMail', 'GETBBSDATA, 'globalcfg.SYSTEM': 'BBSREAD.LASTERROR)
if (right(bbsdata.BBSPATH, 1) ~= ':') & (right(bbsdata.BBSPATH, 1) ~= '/') then bbsdata.BBSPATH = bbsdata.BBSPATH || '/'
/*
** Read configuration and set ARexx clips
*/
call readcfg()
/*
** Process messages
*/
call procmsgs()
/*
** Beat it
*/
signal cleanup
/*
** Some error detection stuff
*/
error:
syntax:
select
when (symbol('BBSREAD.LASTERROR') = 'VAR') then displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br: 'BBSREAD.LASTERROR)
when (symbol('THOR.LASTERROR') = 'VAR') then displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br: 'THOR.LASTERROR)
otherwise displayerror(rc, 'SortMail', 'Line 'sigl' in SortMail.br returned 'rc': 'errortext(rc))
end
break_c:
halt:
cleanup:
/*
** Turn off copyback buffer
*/
address(bbsread)
'BUFMODE ENDCOPYBACK'
/*
** Close progressbar if open
*/
if (symbol('progwin') = 'VAR') & (progwin ~= 0) then do
address(thorport)
'CLOSEPROGRESS REQ 'progwin
progwin = 0
if (symbol('trigcount') = 'VAR') & (trigcount > 0) then do
'CURRENTSYSTEM STEM 'cursys
if (rc > 1) then call displayerror(30, 'SortMail', 'CURRENTSYSTEM: 'THOR.LASTERROR)
if (upper(cursys.CONFNAME) = upper(globalcfg.CONFERENCE)) then 'SHOWCONFERENCE "'globalcfg.CONFERENCE'"'
'UPDATECONFWINDOW'
end
end
/*
** Remove ARexx clip and temporary files
*/
call setclip('SM_Active')
if (exists('T:SortMail.result')) then address command 'Delete T:SortMail.result QUIET'
if (rc ~= 0) then call displayerror(30, 'SortMail', 'GETCONFDATA: 'BBSREAD.LASTERROR)
/*
** Build message stem
*/
address(thorport)
'GETMSGLISTSELECTED STEM 'msglist
if (rc = 0) then do
if (confdata.NAME ~= cursys.CONFNAME) then displayerror(30, 'SortMail', 'You can only multiselect messages for\nprocessing in the Email conference\nconfigured in CfgSortMail.thor.')
do i = 1 to msglist.count; msgs.i = msglist.i; end; msgs.count = msglist.count
multisel = 1
end
else do
address(thorport)
'GETMESSAGEARRAY SYSTEM "'globalcfg.SYSTEM'" CONF "'globalcfg.CONFERENCE'" STEM 'msgs
if (rc = 5) then signal cleanup
else if (rc ~= 0) then call displayerror(30, 'SortMail', 'GETMESSAGEARRAY: 'THOR.LASTERROR)
BDB_ADD_USERS = 9 /* Parser should add users to database. */
MDB_DELETED = 5 /* Message is deleted. */
MDB_MARKED = 10 /* Message is marked. */
MDB_SUPERMARKED = 13 /* Message will not be unmarked as long as this flag is set. */
UDB_DELETED = 0 /* User is deleted */
if (multisel) then do
call notify('You have multi selected ' || msgs.count || ' messages.\n\nDo you want to force these messages\nto be processed by one particular trigger\nor should they be processed normally?', 'Normal|_Force|Abort')
if (result = 0) then signal cleanup
else if (result = 2) then do
do i = 1 to trigger.count; triglist.i = trigger.i.name; end
triglist.count = trigger.count
address(thorport)
'REQUESTLIST INSTEM 'triglist' TITLE "Select a trigger" SIZEGADGET'
if (symbol('text.COMMENT.COUNT') = 'VAR') & (text.COMMENT.COUNT > 0) then do c = 1 to text.COMMENT.COUNT
if (upper(subword(text.COMMENT.c, 1, 1))) = 'RECEIVED:' then do
islocal = 0; leave c
end
end
/*
** Trigger loop
*/
address(bbsread)
do j = 1 to trigger.count
if trigger.j.skip then iterate j
foundmsg = 0; foundcrits = 0
if (multisel) then if (forcetrig = trigger.j.name) then foundmsg = 1
/*
** Search in names, addresses and subject
*/
do k = 1 to trigger.j.search.count while foundmsg = 0
select
when (trigger.j.search.k.type = 'FROMADDR') then do
if (trigger.j.search.k.not) then do
if ~(index(upper(head.FROMADDR), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
else do
if (index(upper(head.FROMADDR), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
end
when (trigger.j.search.k.type = 'FROMNAME') then do
if (trigger.j.search.k.not) then do
if ~(index(upper(head.FROMNAME), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
else do
if (index(upper(head.FROMNAME), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
end
when (trigger.j.search.k.type = 'TOADDR') | (trigger.j.search.k.type = 'TONAME') then do
call parseaddr(0)
if ~(trigger.j.search.k.not) then do
do l = 1 to addrs.COUNT while foundmsg = 0
if (trigger.j.search.k.type = 'TOADDR') & (addrs.l.addr ~= '') & (index(upper(addrs.l.ADDR), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
if (trigger.j.search.k.type = 'TONAME') & (addrs.l.name ~= '') & (index(upper(addrs.l.NAME), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
end
else do
foundcrit = 0
do l = 1 to addrs.COUNT while foundcrit = 0
if (trigger.j.search.k.type = 'TOADDR') & (addrs.l.addr ~= '') & (index(upper(addrs.l.ADDR), upper(trigger.j.search.k.criteria)) > 0) then foundcrit = 1
if (trigger.j.search.k.type = 'TONAME') & (addrs.l.name ~= '') & (index(upper(addrs.l.NAME), upper(trigger.j.search.k.criteria)) > 0) then foundcrit = 1
end
if ~(foundcrit) then foundmsg = 1
drop foundcrit
end
end
when (trigger.j.search.k.type = 'SUBJECT') then do
if trigger.j.search.k.not then do
if ~(index(upper(head.SUBJECT), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
else do
if (index(upper(head.SUBJECT), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
end
when (trigger.j.search.k.type = 'REPLYTO') then do
if trigger.j.search.k.not then do
if ~(index(upper(text.REPLYADDR), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
else do
if (index(upper(text.REPLYADDR), upper(trigger.j.search.k.criteria)) > 0) then foundmsg = 1
end
end
otherwise do
if (trigger.j.search.k.type ~= 'HEADER') & (trigger.j.search.k.type ~= 'BODY') then do
if (symbol('trigger.j.search.k.type') = 'VAR') then call displayerror(5, 'SortMail', 'Unsupported SEARCH type in trigger 'j': ' || trigger.j.search.k.type, msgs.i)
if (rc ~= 0) then displayerror(30, 'SortMail', 'UPDATEBRMESSAGE: 'BBSREAD.LASTERROR, msgs.i)
end
end
message = 'A total of ' || msgs.count || ' messages were scanned.\n'
if trigcount = 0 then message = message || 'No messages were processed by a trigger.\n'
if trigcount > 0 then message = message || trigcount || ' of these were processed by a trigger.\n'
if sucount > 0 then message = message || sucount || ' messages were marked as superunread.\n'
if killcount > 0 then message = message || killcount || ' message copy actions were caught by a kill entry.\n'
if localcount > 0 then message = message || localcount || ' messages were local copies that were removed.\n'
if owncount > 0 then message = message || owncount || ' messages were moved to "' || globalcfg.LOCALTO || '".\n'
if trigskipped = 1 then message = message || '\nNB! One or more triggers used search methods\nnot available in this ARexx script and\nwere skipped. See SortMail.guide.\n\n'
if failcount > 0 then message = message || failcount || ' messages returned an error.'
'UPDATEPROGRESS REQ 'progwin' TOTAL 'cfglength' CURRENT 0 PT "'cursys.BBSNAME': Reading configuration..."'
if (rc = 5) then signal cleanup
else if (rc > 0) then call displayerror(rc, 'SortMail', 'UPDATEPROGRESS: 'THOR.LASTERROR, msgs.i)
do until (seek(cf, 0) = cfglength)
entry = readln(cf); cfgline = cfgline + 1
if (symbol('progwin') = 'VAR') then do
address(thorport)
'UPDATEPROGRESS 'progwin' CURRENT 'seek(cf, 0)
if (rc = 5) then signal cleanup
if (rc ~= 0) then displayerror(rc, 'Read config', 'UPDATEPROGRESS: 'THOR.LASTERROR)
end
address(bbsread)
select
when (upper(subword(entry, 1, 1)) = "SYSTEM") then displayerror(30, 'Read config', 'Found old 2.x configuration file. SortMail has\nchanged the configuration file format in version\n3.0. Please create a new one with CfgSortMail.thor.')
when (upper(subword(entry, 1, 1)) = "GLOBAL") then do
if (rc ~= 0) then call displayerror(30, 'Read config', 'Error in 'cfgfile' line 'cfgline': 'BBSREAD.LASTERROR)
if (symbol('trigger.triggers.groups') = 'VAR') then if (trigger.triggers.groups ~= 'EMail') then trigger.triggers.skip = 1; else trigger.triggers.skip = 0
do
searches = 0; actions = 0
do until (upper(subentry) = 'ENDTRIGGER') | (eof(cf))
subentry = readln(cf); cfgline = cfgline + 1
select
when (upper(subword(subentry, 1, 1)) = 'ACTION') then do
if (rc ~= 0) then call displayerror(30, 'Read config', 'Error in 'cfgfile' line 'cfgline': 'BBSREAD.LASTERROR)
if (symbol('trigger.triggers.search.searches.substr') = 'VAR') then do; trigger.triggers.search.searches.criteria = trigger.triggers.search.searches.substr; drop trigger.triggers.search.searches.substr; end
if ((symbol('trigger.triggers.search.searches.criteria') ~= 'VAR') & (symbol('trigger.triggers.search.searches.pattern') ~= 'VAR')) | ((symbol('trigger.triggers.search.searches.criteria') = 'VAR') & (symbol('trigger.triggers.search.searches.pattern') = 'VAR')) then call displayerror(20, 'SortMail', 'Error in 'cfgfile' line 'cfgline':\nIllegal use of search parameters.')
if (symbol('trigger.triggers.search.searches.pattern') = 'VAR') then trigger.triggers.skip = 1; else trigger.triggers.skip = 0
end
when (eof(cf)) then call displayerror(30, 'Read config', 'Premature end of configuration file 'cfgfile)
when (upper(subword(subentry, 1, 1)) = 'TRIGGER') then call displayerror(30, 'Read config', 'TRIGGER did not end with ENDTRIGGER in 'cfgfile' line 'cfgline)
otherwise nop
end
end
end
trigger.triggers.action.count = actions
trigger.triggers.search.count = searches
if trigger.triggers.skip = 1 then trigskipped = 1
end
otherwise nop
end
trigger.count = triggers
end
end
else do
call displayerror(30, 'Read config', 'Couldn''t open ' || bbsdata.BBSPATH || cfgfile || ' for reading.')